package org.iks.push.serial;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.iks.common.constant.Constant;
import org.iks.common.pojo.message.SerializationType;
import org.iks.push.message.AuthVerifyMessage;
import org.iks.common.pojo.message.ChatMessage;
import org.iks.common.pojo.message.Message;
import org.springframework.lang.Nullable;
import java.io.IOException;
import java.util.Map;

/**
 * Author kzou
 * Date 2024/1/28
 * Description:
 */
@Slf4j
@Getter
@AllArgsConstructor
public enum SerializableType {
    JSON(1) {
        @Override
        public byte[] serialize(Message message) {
            ObjectMapper objectMapper = new ObjectMapper();
            try {
                return objectMapper.writeValueAsString(message).getBytes(Constant.Utf8);
            } catch (JsonProcessingException e) {
                log.warn("json serialize exception for message: " + e.getMessage());
                return null;
            }
        }

        @Override
        public Message deserialize(byte[] data) {
            ObjectMapper objectMapper = new ObjectMapper();
            try {
                Map<String, Object> objectMap = objectMapper.readValue(data, new TypeReference<>() {});
                Integer messageType = (Integer) objectMap.get("messageType");
                Class<?> aClass = Message.actions.get(messageType.byteValue());
                return (Message)objectMapper.readValue(data, aClass);
            } catch (IOException e) {
                log.warn("json deserialize exception for message: " + e.getMessage());
                return null;
            }
        }
    },

    ;

    private final Integer code;

    @Nullable
    public abstract byte[] serialize(Message message);

    @Nullable
    public abstract Message deserialize(byte[] data);

    public static SerializationType of(Integer code) {
        SerializationType[] values = SerializationType.values();
        for (SerializationType value : values) {
            if (value.getCode() == code) {
                return value;
            }
        }
        return null;
    }

    static {
        Message.actions.put(Message.AuthVerifyMessageType, AuthVerifyMessage.class);
        Message.actions.put(Message.ChartMessageType, ChatMessage.class);
    }

}
